using System;
using System.Collections.Generic;
using Mgrs;
using UnityEngine;

namespace Commons
{
    /**
     * 通用 MonoBehaviour
     * 目前内部以封装消息机制
     */
    public abstract class ComMonoBehaviour : MonoBehaviour
    {
        private readonly List<MsgRecord> _msgRecords = new();

        private void OnDestroy()
        {
            OnBeforeDestroy();
            UnRegisterMsgAll();
        }

        /**注销所有消息 */
        private void UnRegisterMsgAll()
        {
            _msgRecords.ForEach(record =>
            {
                MsgMgr.UnRegisterMsg(record.MsgName, record.OnMsgReceived);
                record.Recycle();
            });

            _msgRecords.Clear();
        }

        protected abstract void OnBeforeDestroy();

        /**
         * <summary>注销消息</summary>
         * <param name="msgName">注销的消息名</param>
         * <param name="onMsgReceived" >注销的消息方法</param>
         */
        protected void RegisterMsg(string msgName, Action<object> onMsgReceived)
        {
            MsgMgr.RegisterMsg(msgName, onMsgReceived);
            _msgRecords.Add(MsgRecord.Allocate(msgName, onMsgReceived));
        }

        /**
         * <summary>注销消息</summary>
         * <param name="msgName">注销的消息名</param>
         * <param name="onMsgReceived" >注销的消息方法</param>
         */
        protected void UnRegisterMsg(string msgName, Action<object> onMsgReceived = null)
        {
            var records = _msgRecords.FindAll(record =>
                record.MsgName == msgName && (onMsgReceived == null || record.OnMsgReceived == onMsgReceived));

            records.ForEach(record =>
            {
                MsgMgr.UnRegisterMsg(record.MsgName, record.OnMsgReceived);
                _msgRecords.Remove(record);
                record.Recycle();
            });

            records.Clear();
        }

        /**
         * <summary>发送消息</summary>
         * <param name="msgName">发送的消息名</param>
         * <param name="data">发送的数据</param>
         */
        protected void SendMsg(string msgName, object data = null)
        {
            MsgMgr.Send(msgName, data);
        }
    }
}